using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Roslyn.Compilers.CSharp;

namespace ContentOverContainer.Common
{
    public class MethodReplacement
    {
        public ExpressionSyntax InvocationCall { get; set; }
        public MethodDeclarationSyntax MethodDecl { get; set; }
    }

    public class ParameterPair
    {
        public TypeSyntax Type { get; set; }
        public ExpressionSyntax Name { get; set; }
    }

    public static class MethodComposer
    {
        public static string RandomMethodName(string pMethodName)
        {
            return "method"+ pMethodName + RandomTokenString();
        }

        public static string RandomVarialbleName()
        {
            return "var" + RandomTokenString();
        }

        private static string RandomTokenString()
        {
            return Guid.NewGuid().ToString().Replace('-', '_');
        }

        public static MethodReplacement BuildMethod(string pMethodName, BlockSyntax pMethodBody, List<ParameterPair> pParameters, string pReturnType = "dynamic")
        {
            var methodName = MethodComposer.RandomMethodName(pMethodName);
            //create inline replacement
            string parameterList = String.Empty;
            foreach (var parameterPair in pParameters)
            {
                parameterList += parameterPair.Name + ",";
            }
            parameterList = parameterList.TrimEnd(',');
            var invoc = String.Format("{0}({1})", methodName, parameterList);
            var replacement = Syntax.ParseExpression(invoc);

            //create new methodsyntax            
            MethodDeclarationSyntax method = Syntax.MethodDeclaration(Syntax.ParseTypeName(pReturnType), methodName);
            //create param list
            if ((pParameters != null) && (pParameters.Any()))
            {
                string methodParams = String.Empty;
                foreach (var parameterPair in pParameters)
                {
                    if (parameterPair.Name is ObjectCreationExpressionSyntax) continue;
                    methodParams += parameterPair.Type + " " + parameterPair.Name + ",";
                }
                if (!String.IsNullOrWhiteSpace(methodParams))
                {
                    methodParams = "(" + methodParams.TrimEnd(',') + ")";
                    method = method.WithParameterList(Syntax.ParseParameterList(methodParams));
                }
            }

            method = method.WithBody(pMethodBody);
            return new MethodReplacement() { InvocationCall = replacement, MethodDecl = method };
        }
    }
}
